﻿using Component;
using Painter.Component;
using Painter.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace Painter
{
    /// <summary>
    /// LayerCanvas.xaml 的交互逻辑
    /// </summary>
    public partial class LayerCanvas : UserControl, INotifyPropertyChanged
    {
        
        public int mActiveLayer { get; set; }
        public List<LayerState> mOrderBackup = new List<LayerState>();
        public event PropertyChangedEventHandler PropertyChanged;

        //public Cursor mLastCursor { get; set; }
        public string FullFileName { get; set; }
        public List<PaintCanvas> CanvasCollection
        {
            get
            {
                return gridLayout.Children.Cast<UIElement>().
                    Where(o => o is PaintCanvas).Cast<PaintCanvas>().Reverse().ToList();
            }
        }
        public PaintCanvas ActiveCanvas
        {
            get
            {
                LayerState item = mOrderBackup.ElementAt(mActiveLayer);
                PaintCanvas active = gridLayout.Children[item.layer_index] as PaintCanvas;
                return active;
            }
        }
        public string[] Layers
        {
            get
            {
                return mOrderBackup.Select(o => o.layer_name).ToArray();
            }
        }
        public CommandStack mCmdStack { get; set; }

        public LayerCanvas()
        {
            mActiveLayer = 1;
            InitializeComponent();
            mCmdStack = new CommandStack(CanvasCollection.Select(o => o.Strokes).ToList());

            //图层顺序
            mOrderBackup.Add(new LayerState() { layer_index = 0, bVisible = true, layer_name = "背景" });
            mOrderBackup.Add(new LayerState() { layer_index = 1, bVisible = true, layer_name = "图层1" });

            //undo、redo
            CanvasCollection.ForEach(o => o.Strokes.StrokesChanged += Strokes_StrokesChanged);
            CanvasCollection.ForEach(o => o.SelectionMoving += PaintCanvas_SelectionMoving);
            CanvasCollection.ForEach(o => o.SelectionResizing += PaintCanvas_SelectionResizing);
        }

        #region 图层
        public void AddLayer(string layerName)
        {
            mOrderBackup.Add(new LayerState() { layer_index = gridLayout.Children.Count - 1, bVisible = true, layer_name= layerName });
            gridLayout.Children.Insert(gridLayout.Children.Count - 1,new PaintCanvas() { Cursor = PaintSettings.inst().Cursor});
        }
        public void DelLayer(int index)
        {
            LayerState item = mOrderBackup.ElementAt(index);
            gridLayout.Children.RemoveAt(item.layer_index);

            mOrderBackup.RemoveAt(index);
            mOrderBackup.ForEach(o => { if (o.layer_index > item.layer_index) o.layer_index -= 1; });
        }
        public void LayerPanel_mLayerStatusChanged(LayerState state)
        {
            try {
                gridLayout.Children[state.layer_index].Visibility = (state.bVisible ? Visibility.Visible : Visibility.Hidden);
                grid.IsHitTestVisible = mOrderBackup[mActiveLayer].bVisible  ? false : true;
            }
            catch { }
        }
        public void LayerPanel_mLayerSelectChanged(int nIndex)
        {
            try{
                mActiveLayer = nIndex;
                if (nIndex >= 0)
                {
                    LayerState item = mOrderBackup[nIndex];
                    PaintCanvas canvas = gridLayout.Children[item.layer_index] as PaintCanvas;

                    gridLayout.Children.Remove(canvas);
                    gridLayout.Children.Insert(gridLayout.Children.Count - 1, canvas);
                    grid.IsHitTestVisible = (item.bVisible ? false : true);

                    mOrderBackup.ForEach(o => { if (o.layer_index > item.layer_index) o.layer_index -= 1; });
                    item.layer_index = mOrderBackup.Count - 1;
                }
            }catch { }
        }
        #endregion

        #region Undo\Redo
        private void PaintCanvas_SelectionMoving(object sender, InkCanvasSelectionEditingEventArgs e)
        {
            Rect newRect = e.NewRectangle;
            Rect oldRect = e.OldRectangle;
            mCmdStack.Enqueue(new SelectionMovedOrResizedCI(mCmdStack,
                new StrokeCollection(CanvasCollection.SelectMany(o => o.GetSelectedStrokes())),
                newRect, oldRect));
        }
        private void PaintCanvas_SelectionResizing(object sender, InkCanvasSelectionEditingEventArgs e)
        {
            Rect newRect = e.NewRectangle;
            Rect oldRect = e.OldRectangle;
            mCmdStack.Enqueue(new SelectionMovedOrResizedCI(mCmdStack, 
                new StrokeCollection(CanvasCollection.SelectMany(o=>o.GetSelectedStrokes())),
                newRect, oldRect));
        }
        private void Strokes_StrokesChanged(object sender, StrokeCollectionChangedEventArgs e)
        {
            mCmdStack.Enqueue(new StrokesAddedOrRemovedCI(mCmdStack, CanvasCollection.First().EditingMode,
                new StrokeCollection(e.Added), new StrokeCollection(e.Removed), sender as StrokeCollection));
        }
        #endregion

        public void Canvas_ZoomIn(double scale)
        {
            ScaleData scale_data = ScaleData.Find_CreateScaleData(scaleborder);
            scale_data.ZoomInOut(true);
            (scaleborder.Child as GroupScroll).UpdateLayout();
             
        }
        public void Canvas_ZoomOut(double scale)
        {
            ScaleData scale_data = ScaleData.Find_CreateScaleData(scaleborder);
            scale_data.ZoomInOut(false);
            (scaleborder.Child as GroupScroll).UpdateLayout();
        }
        public void Canvas_Reset()
        {
            ScaleData scale_data = ScaleData.Find_CreateScaleData(scaleborder);
            scale_data.Scale = 1;
            (scaleborder.Child as GroupScroll).UpdateLayout();
        }
        public void SaveFile(string fileName)
        {
            RenderTargetBitmap renderBitmap = new RenderTargetBitmap((int)ActiveCanvas.ActualWidth,
                (int)ActiveCanvas.ActualHeight, 0, 0, PixelFormats.Default);
            renderBitmap.Render(renderBackground);
            CanvasCollection.ForEach(o=>renderBitmap.Render(o));
            BmpBitmapEncoder encoder = new BmpBitmapEncoder();
            encoder.Frames.Add(BitmapFrame.Create(renderBitmap));
            using (Stream stm = File.Create(fileName))
                encoder.Save(stm);
        }
        public RenderTargetBitmap SaveBitmap()
        {
            RenderTargetBitmap renderBitmap;
            AAdorner adorner = AdornerControl.GetAdorner(ActiveCanvas);
            if (adorner!=null){
                renderBitmap = new RenderTargetBitmap((int)adorner.mGeometry.Bounds.Width, 
                    (int)adorner.mGeometry.Bounds.Height,0,0,PixelFormats.Default);
                renderBitmap.Render(renderBackground);
                renderBitmap.Render(adorner.mImage);
            }
            else{
                renderBitmap = new RenderTargetBitmap((int)ActiveCanvas.ActualWidth,
                    (int)ActiveCanvas.ActualHeight, 0, 0, PixelFormats.Default);
                renderBitmap.Render(renderBackground);
                CanvasCollection.ForEach(o => renderBitmap.Render(o));
            }
            return renderBitmap;
        }

        #region 右键菜单
        private void Cut_MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }
        private void Copy_MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }
        private void Paste_MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }
        private void CutSelect_MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }
        private void SelectAll_MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }
        private void AlterSelect_MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }
        private void Delete_MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }

        private void Rotate_MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }

        private void ChangSize_MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }
        private void OpsiteColor_MenuItem_Click(object sender, RoutedEventArgs e)
        {

        }
        #endregion
    }
}
